package com.zh.idservice.ordercode.service.impl;

import com.zh.idservice.ordercode.service.OrderCodeService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service(value = "orderCodeService")
public class OrderCodeServiceImpl implements OrderCodeService {
    private static final Logger LOGGER = LoggerFactory.getLogger(OrderCodeServiceImpl.class);

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RedissonClient redissonClient;

    private static final String ORDERCODE_SEQUENCE_KEY = "OrderCode_Sequence";
    private static final String LOCK = "SetExpire_Lock";

    private String getPrefix(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        int year = calendar.get(Calendar.YEAR);
        int day = calendar.get(Calendar.DAY_OF_YEAR);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minutes = calendar.get(Calendar.MINUTE);

        String dayFmt = String.format("%03d", day);
        String hourFmt = String.format("%02d", hour);
        String minutesFmt = String.format("%02d", minutes);

        return year + dayFmt + hourFmt + minutesFmt;
    }

    @Override
    public String createOrderCode() {
        Date currentDate = new Date();
        String prefix = getPrefix(currentDate);
        String orderId = "";
        Long incr = redisTemplate.opsForValue().increment(ORDERCODE_SEQUENCE_KEY, 1L);
        setExpire(currentDate);
        orderId = prefix + String.format("%05d", incr);
        return orderId;
    }

    /**
     * TODO 集群部署需要增加分布式锁
     * 设置整点过期时间
     */
    private synchronized void setExpire(Date currentDate) {
        RLock lock = redissonClient.getLock(LOCK);
        try {
            if (lock.tryLock(10L, 10L, TimeUnit.SECONDS)) {
                if (redisTemplate.getExpire(ORDERCODE_SEQUENCE_KEY) < 0) {// key 已经过期了
                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    LOGGER.info(">>> 当前时间:{}", dateFormat.format(currentDate));

                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(currentDate);

                    int second = calendar.get(Calendar.SECOND);
                    calendar.add(Calendar.MINUTE, 1);
                    Long expireAtTime = calendar.getTime().getTime() - second * 1000L;
                    Date expireAtDate = new Date(expireAtTime);

                    redisTemplate.expireAt(ORDERCODE_SEQUENCE_KEY, expireAtDate);
                    LOGGER.info(">>> 过期时间:{}", dateFormat.format(expireAtDate));
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}
